package org.wxd.common.utils.md5;

import org.wxd.common.utils.Assert;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * md5工具类，对应前端的md5.js对应转
 * Created by wangxd on 2017/3/13.
 */
public class MD5Utli {

    private static final String KEY_MD5 = "MD5";
    // 全局数组
    private static final String[] strDigits = {"0", "1", "A", "B", "2", "3",
            "4", "C", "D", "5", "6", "7", "8", "9", "E", "F"};

    // 返回形式为数字跟字符串
    private static String byteToArrayString(byte bByte) {
        return byteToArrayString(bByte,strDigits);
    }
    private static String byteToArrayString(byte bByte,String[] strDigits) {
        int iRet = bByte;
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }


    // 转换字节数组为16进制字串
    private static String byteToString(byte[] bByte) {
       return byteToString(bByte,strDigits);
    }
    // 转换字节数组为16进制字串
    private static String byteToString(byte[] bByte,String[] strDigits) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i],strDigits));
        }
        return sBuffer.toString();
    }

    /**
     * MD5加密
     * 默认strDigits：{"0", "1", "A", "B", "2", "3" "4", "C", "D", "5", "6", "7", "8", "9", "E", "F"};
     * @param str
     * @return
     * @throws Exception
     */
    public static String getMD5Code(String str) throws MD5StrNullOrDigitsNullException,MD5Exception {
        if (str == null) throw new MD5StrNullOrDigitsNullException("str is null");
        Assert.notNull(str,"str cant not be null.");
        return getMD5Code(str,strDigits);
    }

    /**
     * 自定义映射编码
     * @param str
     * @param strDigits
     * @return
     * @throws Exception
     */
    public static String getMD5Code(String str,String[] strDigits) throws MD5StrNullOrDigitsNullException,MD5Exception {
        if (str == null || strDigits == null || strDigits.length == 0) throw new MD5StrNullOrDigitsNullException("str is null or strDigits is null or empty.");
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance(KEY_MD5);
        } catch (NoSuchAlgorithmException e) {
            throw new MD5Exception(e.getMessage(),e);
        }
        return byteToString(md.digest(str.getBytes()),strDigits);
    }

}
